package com.tbit.main.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.tbit.main.constant.*;
import com.tbit.main.dao.core.BatteryMachineDao;
import com.tbit.main.exception.BaseException;
import com.tbit.main.pojo.*;
import com.tbit.main.pojo.bo.CommonControlParamBO;
import com.tbit.main.service.*;
import com.tbit.main.util.DateTimeUtil;
import com.tbit.main.util.LogUtil;
import com.tbit.main.util.StringUtil;
import org.apache.commons.collections4.ListUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author LMY
 * @create 2021-05-27 14:33
 * 电池车辆绑定表
 */
@Service("batteryMachineService")
public class BatteryMachineServiceImpl implements BatteryMachineService {

    @Autowired
    private BatteryMachineDao batteryMachineDao;
    @Autowired
    private MachineStatusService machineStatusService;
    @Autowired
    private AccountConfigService accountConfigService;
    @Autowired
    private CalibrateService calibrateService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private TerControlService terControlService;
    @Autowired
    private AccountUserService accountUserService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private PowerChangeLogService powerChangeLogService;
    @Autowired
    private PowerChangeLogExpandService powerChangeLogExpandService;
    @Autowired
    private BatteryService batteryService;
    @Autowired
    private BatteryLogService batteryLogService;
    @Autowired
    private MQProducer mqProducer;
    @Autowired
    private DataService dataService;
    @Autowired
    private MachineService machineService;
    @Autowired
    private RideLogService rideLogService;
    @Autowired
    private RoleService roleService;

    @Override
    public void control(AccountUser accountUser, String serNO, Machine machine, Integer type) {

        /**获取最后状态*/
        MachineStatus machineStatus = machineStatusService.getByMachineId(machine.getMachineId());
        if (machineStatus == null) {
            throw new BaseException("Machine.notActive");
        }

        LogUtil.info("[" + machine.getMachineNO() + "]开始换电");

        /**换电阈值配置*/
        AccountConfig accountConfig = accountConfigService.getByAccountId(machine.getAccountId());
        Integer values = dataService.getRoleConfig(accountUser.getAccountUserType() + RoleConfigConstant.MAIN_CHANGE_BATTERY);

        /**普通运维人员不能还低于指定阈值的车辆*/
        if (accountConfig != null && machineStatus.getSocPercent() > accountConfig.getSocLimit()) {
            LogUtil.warn("[" + machine.getMachineNO() + "]运维无效换电");
            if (values != null && values.equals(1)) {
                throw new BaseException("Machine.soc.over");
            }
        }

        /**是否添加*/
        Boolean isAdd = true;
        if (accountConfig == null) {
            isAdd = true;
        } else {
            /**普通运维人员必须要在指定电量以下添加才有效*/
            if (values != null && values.equals(1)) {
                if (machineStatus.getSocPercent() <= accountConfig.getSocLimit()) {
                    isAdd = true;
                } else {
                    isAdd = false;
                }
            }
        }


        if (isAdd) {
            /**记录换电记录*/
            PowerChangeLog pcl = new PowerChangeLog();
            pcl.setAccountId(machine.getAccountId());
            pcl.setMachineId(machine.getMachineId());
            pcl.setUserCode(machine.getUserCode());
            pcl.setMachineNO(machine.getMachineNO());
            pcl.setUserMainId(accountUser.getAccountUserId());
            pcl.setChangeTime(DateTimeUtil.getNowTime());
            pcl.setOldSoc(machineStatus.getSocPercent());
            pcl.setRemark("电池管理换电,换电前电压=" + machineStatus.getBatteryEU() + ";");
            pcl.setMachineType(machine.getMachineType());
            pcl.setIsValid(0);
            pcl.setPowerChangeCheck(0);

            /**换电判断缓存*/
            redisService.add(RedisConstant.REDIS_TER_BATTERY_CHANGE + machine.getMachineNO(), JSONObject.toJSONString(pcl));

        }

        terControlService.commonControl(new CommonControlParamBO(serNO, machine, type, "开电池锁(change)"));

    }

    @Override
    public void insert(BatteryMachine batteryMachine) {
        batteryMachineDao.insert(batteryMachine);
    }

    @Override
    public void update(Integer machineId, Integer batteryId, String batteryNO, Integer accountUserId) {
        Map<String, Object> map = new HashMap<>();
        map.put("machineId", machineId);
        map.put("batterId", batteryId);
        map.put("batteryNO", batteryNO);
        map.put("accountUserId", accountUserId);
        map.put("boundTime", DateTimeUtil.getNowTime());
        batteryMachineDao.update(map);
    }

    @Override
    public BatteryMachine getByMachineId(Integer machineId) {
        return batteryMachineDao.getByMachineId(machineId);
    }

    @Override
    public BatteryMachine getByBatteryNO(String batteryNO) {
        return batteryMachineDao.getByBatteryNO(batteryNO);
    }


    @Override
    public List<PowerChangeLogSta> groupByTime(Integer agentId, Integer userType, Integer usermainId, String startTime, String endTime) {
        List<PowerChangeLogSta> dlses = new ArrayList<PowerChangeLogSta>();

        /**查询代理商运维账号*/
        List<Integer> accountUserIds = new ArrayList<Integer>();
        /**判断当前账号是不是运维人员*/
        if (roleService.getRoleCode(userType).equals(1)) {
            accountUserIds.add(usermainId);
        }

        Map<String, Object> params = new HashMap<String, Object>();
        params.put(DaoParamConstant.accountId, agentId);
        params.put("accountUserId", StringUtil.getListString(accountUserIds));
        params.put(DaoParamConstant.startTime, startTime);
        params.put(DaoParamConstant.endTime, endTime);
        dlses = batteryMachineDao.groupByTime(params);

        List<PowerChangeLogSta> dlsefilters = new ArrayList<PowerChangeLogSta>();
        if (dlses.size() > 0) {
            for (PowerChangeLogSta dls : dlses) {
                AccountUser au = accountUserService.getById(dls.getUserMainId());
                if (au != null) {
                    dls.setName(au.getName());
                    dls.setPhone(au.getPhone());
                    dlsefilters.add(dls);
                }
            }
        }
        return dlsefilters;
    }

    @Override
    public List<BatteryMachine> getByTime(Integer accountId, Integer userMainId, String startTime, String endTime) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put(DaoParamConstant.accountId, accountId);
        params.put("accountUserId", userMainId);
        params.put(DaoParamConstant.startTime, startTime);
        params.put(DaoParamConstant.endTime, endTime);
        return batteryMachineDao.getByTime(params);
    }

    @Override
    public List<BatteryMachine> getByBatterIds(List<Integer> batterIds) {
        return null;
    }

    @Override
    public List<BatteryMachine> getByMachineIds(List<Integer> machineIds) {

        List<BatteryMachine> batteryMachines = new LinkedList<>();
        List<List<Integer>> machineIdList = ListUtils.partition(machineIds, 900);
        for (List<Integer> ids : machineIdList) {
            batteryMachines.addAll(batteryMachineDao.getByMachineIds(StringUtil.getListString(ids)));
        }
        return batteryMachines;
    }

    @Override
    public void changeCheck(AccountUser accountUser, String userCode, String batteryNO, Integer mapType, Double lon, Double lat) {

        String time = DateTimeUtil.getNowTime();

        Battery batteryNew = batteryService.getByNO(batteryNO);

        if (!batteryNew.getState().equals(BatteryConstant.Battery_State_WSY)) {
            throw new BaseException("Battery.batteryNo.notCKLQ");
        }

        if (!batteryNew.getAccountUserId().equals(accountUser.getAccountUserId())) {
            throw new BaseException("System.noPower");
        }

        Machine machine = machineService.getByUseCode(userCode);

        Battery batteryOld = batteryService.getByUserCode(userCode);

        /** 查询换电记录 */
        String pcl = redisService.get(RedisConstant.REDIS_TER_BATTERY_CHANGE + machine.getMachineNO());
        if (pcl != null) {
            PowerChangeLog pclNew = new PowerChangeLog();
            try {
                pclNew = JSONObject.parseObject(pcl, PowerChangeLog.class);
            } catch (JSONException e) {
                redisService.del(RedisConstant.REDIS_TER_BATTERY_CHANGE + machine.getMachineNO());
            }


            pclNew.setPowerChangeCheck(1);
            pclNew.setChangeTime(time);
            pclNew.setBatteryNO(batteryNO);
            pclNew.setBatteryId(batteryNew.getBatteryId());
            pclNew.setLat(lat);
            pclNew.setLon(lon);
            powerChangeLogService.insert(pclNew);

            /**换电判断缓存*/
            redisService.add(RedisConstant.REDIS_TER_BATTERY_CHANGE + machine.getMachineNO(), JSONObject.toJSONString(pclNew));

            /**添加到redismap*/
            redisService.set(RedisConstant.REDIS_TER_BIKE_BATTERY_CHANGE_MAP, machine.getMachineNO(), String.valueOf(System.currentTimeMillis()));

            PowerChangeLogExpand powerChangeLogExpand = new PowerChangeLogExpand();
            powerChangeLogExpand.setUserCode(userCode);
            powerChangeLogExpand.setAccountId(machine.getAccountId());
            powerChangeLogExpand.setMachineId(dataService.getMachineIdUserCode(userCode));
            if (batteryOld != null) {
                powerChangeLogExpand.setBatteryNOOld(batteryOld.getBatteryNO());
                powerChangeLogExpand.setBatteryIdOld(batteryOld.getBatteryId());
            }
            powerChangeLogExpand.setBatteryNONew(batteryNO);
            powerChangeLogExpand.setBatteryIdNew(dataService.getBatteryId(batteryNO));
            powerChangeLogExpand.setAccountUserId(accountUser.getAccountUserId());
            powerChangeLogExpand.setAddTime(time);
            powerChangeLogExpand.setPowerChangeId(pclNew.getPowerChangeLogId());

            /**记录运维事件轨迹*/
            TerPosition terPosition = new TerPosition();
            terPosition.setMachineNO(accountUser.getPhone());
            terPosition.setLat(lat);
            terPosition.setLon(lon);
            terPosition.setDt(time);
            terPosition.setExData(HistoryExData.UW + "=" + HistoryExData.HD + ";");
            calibrateService.calTerPosition(terPosition, mapType, SysConstant.ORIGINAL);
            historyService.insert(terPosition);

            powerChangeLogExpand.setLatC(terPosition.getLatC());
            powerChangeLogExpand.setLonC(terPosition.getLonC());
            powerChangeLogExpandService.insert(powerChangeLogExpand);

            /**修改换电日志拓展表*/
            if (batteryOld != null) {
                PowerChangeLogExpand powerChangeLogExpandOld = powerChangeLogExpandService.getUserLast(batteryOld.getBatteryNO());
                if (powerChangeLogExpandOld != null) {
                    List<Integer> rideLogTime = rideLogService.getMachineIdTime(machine.getMachineId(), powerChangeLogExpandOld.getAddTime(), time);
                    rideLogTime = rideLogTime.stream().filter(Objects::nonNull).collect(Collectors.toList());
                    Integer times = rideLogTime.stream().mapToInt(s -> s).sum();

                    List<RideLog> mileageList = rideLogService.getMachineIdStartTime(machine.getMachineId(), powerChangeLogExpandOld.getAddTime(), time);
                    List<Double> mileageS = mileageList.stream().map(RideLog::getMileage).collect(Collectors.toList());
                    Double mileage = mileageS.stream().mapToDouble(s -> s).sum();
                    powerChangeLogExpandOld.setMileage(mileage);
                    powerChangeLogExpandOld.setRideTime(times);
                    powerChangeLogExpandService.update(powerChangeLogExpandOld);

                    /**推送bms 服务*/
                    TerControlMsg<PowerChangeLogExpand> terControlMsgService = new TerControlMsg<PowerChangeLogExpand>();
                    terControlMsgService.setFeedback("tbit_uqbike_push_bmsService");
                    terControlMsgService.setMsgId(GatewayProtocol.MQ_MSG_ID_AROUND_MSG_PUSH);
                    terControlMsgService.setData(powerChangeLogExpandOld);
                    /**发送到MQ*/
                    mqProducer.sendDataToQueue("tbit_uqbike_push_bmsService", JSON.toJSONString(terControlMsgService));
                }
            }


            /**推送bms 分析*/
            TerControlMsg<PowerChangeLogExpand> terControlMsg = new TerControlMsg<PowerChangeLogExpand>();
            terControlMsg.setFeedback("tbit_uqbike_push_bms");
            terControlMsg.setMsgId(GatewayProtocol.MQ_MSG_ID_AROUND_MSG_PUSH);
            terControlMsg.setData(powerChangeLogExpand);
            /**发送到MQ*/
            mqProducer.sendDataToQueue("tbit_uqbike_push_bms", JSON.toJSONString(terControlMsg));

        }

        if (batteryOld != null) {
            batteryService.updateIdState(batteryOld.getBatteryNO(), userCode, accountUser.getAccountUserId(), BatteryConstant.Battery_State_DRK, null);
            batteryLogService.insert(batteryOld.getBatteryNO(), accountUser.getAccountUserId(), BatteryConstant.Battery_Type_JB, "车辆编码: " + userCode);
        }

        batteryService.updateIdStateCode(batteryNO, userCode, accountUser.getAccountUserId(), BatteryConstant.Battery_State_SYZ);

        redisService.add(RedisConstant.PUSH_BMS_Machine + dataService.getMachineNO(userCode), batteryNO);

        batteryLogService.insert(batteryNO, accountUser.getAccountUserId(), BatteryConstant.Battery_Type_BD, "车辆编码: "+userCode);

    }

    @Override
    public List<BatteryMachine> getByAccountId(Integer accountId) {
        return batteryMachineDao.getByAccountId(accountId);
    }

    @Override
    public List<BatteryMachine> getByRegionIds(List<Integer> regionIds) {
        return batteryMachineDao.getByRegionIds(StringUtil.getListString(regionIds));
    }
}
